﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Framework.Common.Reflection.RunSharpEmit;
using System.Reflection.Emit;
using Framework.Common.Reflection;
using System.Reflection;
namespace Framework.Common.Extention
{
    /// <summary>
    /// 此扩展用于sqlbulkcopy中通过实体类创建datatable
    /// </summary>
    public static class ToDatatableExtension
    {
        public static DataTable GetDataTable<T>(this IEnumerable<T> source)
        {
            var dynamicMethod = GetDynamicMethod<T>();
            if (dynamicMethod == null)
                return null;
            return dynamicMethod(source);
        }


        #region meta
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <typeparam name="TFunc">委托类型</typeparam>
        /// <param name="paramType"></param>
        /// <returns></returns>
        private static Func<IEnumerable<T>, DataTable> GetDynamicMethod<T>()
        {
            return DynamicMethodCreate.CreateFunc<IEnumerable<T>, DataTable>((cg) =>
                  {
                      PropertyInfo[] properties = typeof(T).GetProperties();
                      Operand dt = cg.Local(Exp.New(typeof(DataTable)));
                      foreach (var prop in properties)
                      {
                          cg.Invoke(dt.Property("Columns"), "Add", prop.Name, prop.PropertyType);
                      }
                      Operand objT = cg.ForEach(typeof(T), cg.Arg("p0"));
                      {
                          Operand dr = cg.Local(dt.Invoke("NewRow"));
                          foreach (var prop in properties)
                          {
                              cg.Assign(dr[prop.Name], objT.Property(prop.Name));
                          }
                          cg.Invoke(dt.Property("Rows"), "Add", dr);
                      }
                      cg.End();
                      cg.Return(dt);
                  }
             , typeof(T).GetHashCode().ToString() + "ToDataTable");
        }
        #endregion
    }
}
